﻿using System.Runtime.CompilerServices;

namespace LxBasic
{
    internal static class FloatMathHelper
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static (double sum, double error) QuickTwoSum(double a, double b)
        {
            double num = a + b;
            return (num, b - (num - a));
        }

        public static Float128 QuickTwoSumD(double a, double b)
        {
            double num = a + b;
            return new Float128(num, b - (num - a));
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static (double sum, double error) TwoSum(double a, double b)
        {
            double num = a + b;
            double num2 = num - a;
            return (num, a - (num - num2) + (b - num2));
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static Float128 TwoSumD(double a, double b)
        {
            double num = a + b;
            double num2 = num - a;
            return new Float128(num, a - (num - num2) + (b - num2));
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static (double diff, double error) QuickTwoDiff(double a, double b)
        {
            double num = a - b;
            return (num, a - num - b);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static (double sum, double error) TwoDiff(double a, double b)
        {
            double num = a - b;
            double num2 = num - a;
            return (num, a - (num - num2) - (b + num2));
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static (double sqr, double error) Square(double a)
        {
            double num = a * a;
            (double high, double low) = Split(a);
            return (num, high * high - num + 2.0 * high * low + low * low);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static (double high, double low) Split(double a)
        {
            double num = 134217729.0 * a;
            double num2 = num - (num - a);
            return (num2, a - num2);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static (double product, double error) TwoProd(double a, double b)
        {
            double num = a * b;
            (double high1, double low1) = Split(a);
            (double high2, double low2) = Split(b);
            return (num, high1 * high2 - num + high1 * low2 + low1 * high2 + low1 * low2);
        }
    }
}
//备份
//internal static class MathHelper
//{
//    [MethodImpl(MethodImplOptions.AggressiveInlining)]
//    public static (double sum, double error) QuickTwoSum(double a, double b)
//    {
//        double num = a + b;
//        return (num, b - (num - a));
//    }

//    public static DdReal QuickTwoSumD(double a, double b)
//    {
//        double num = a + b;
//        return new DdReal(num, b - (num - a));
//    }

//    [MethodImpl(MethodImplOptions.AggressiveInlining)]
//    public static (double sum, double error) TwoSum(double a, double b)
//    {
//        double num = a + b;
//        double num2 = num - a;
//        return (num, a - (num - num2) + (b - num2));
//    }

//    [MethodImpl(MethodImplOptions.AggressiveInlining)]
//    public static DdReal TwoSumD(double a, double b)
//    {
//        double num = a + b;
//        double num2 = num - a;
//        return new DdReal(num, a - (num - num2) + (b - num2));
//    }

//    [MethodImpl(MethodImplOptions.AggressiveInlining)]
//    public static (double diff, double error) QuickTwoDiff(double a, double b)
//    {
//        double num = a - b;
//        return (num, a - num - b);
//    }

//    [MethodImpl(MethodImplOptions.AggressiveInlining)]
//    public static (double sum, double error) TwoDiff(double a, double b)
//    {
//        double num = a - b;
//        double num2 = num - a;
//        return (num, a - (num - num2) - (b + num2));
//    }

//    [MethodImpl(MethodImplOptions.AggressiveInlining)]
//    public static (double sqr, double error) Square(double a)
//    {
//        double num = a * a;
//        (double high, double low) tuple = Split(a);
//        double item = tuple.high;
//        double item2 = tuple.low;
//        return (num, item * item - num + 2.0 * item * item2 + item2 * item2);
//    }

//    [MethodImpl(MethodImplOptions.AggressiveInlining)]
//    public static (double high, double low) Split(double a)
//    {
//        double num = 134217729.0 * a;
//        double num2 = num - (num - a);
//        return (num2, a - num2);
//    }

//    [MethodImpl(MethodImplOptions.AggressiveInlining)]
//    public static (double product, double error) TwoProd(double a, double b)
//    {
//        double num = a * b;
//        (double high, double low) tuple = Split(a);
//        double item = tuple.high;
//        double item2 = tuple.low;
//        (double high, double low) tuple2 = Split(b);
//        double item3 = tuple2.high;
//        double item4 = tuple2.low;
//        return (num, item * item3 - num + item * item4 + item2 * item3 + item2 * item4);
//    }
//}